{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 语法\n",
    "```\n",
    "def func_name(param1, param2, ..., paramN = default—value):\n",
    "    statements\n",
    "    return/yield value\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 110,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Got a message: Hello World, name = 'unknow'\n",
      "Got a message: 你好, name = '征哥'\n"
     ]
    }
   ],
   "source": [
    "#函数解决代码复用问题\n",
    "def my_func(message, name = \"unknow\"):\n",
    "    print(f'Got a message: {message}, {name = }')\n",
    "\n",
    "my_func('Hello World')\n",
    "my_func('你好', '征哥')    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def fun_yield():\n",
    "    x = 1\n",
    "    print(\"=====1\")\n",
    "    yield x\n",
    "    print(\"=====2\")\n",
    "    x = x * 2\n",
    "    yield x\n",
    "    print(\"=====3\")\n",
    "    x = x * 2\n",
    "    yield x\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 112,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "=====1\n",
      "1\n",
      "=====2\n",
      "2\n",
      "=====3\n",
      "4\n"
     ]
    }
   ],
   "source": [
    "for i in fun_yield():\n",
    "    print(i)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 113,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[1, 4, 9, 16, 25, 36, 49, 64, 81]"
      ]
     },
     "execution_count": 113,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    ">>> list(map(lambda x: x * x, [1, 2, 3, 4, 5, 6, 7, 8, 9]))\n",
    "[1, 4, 9, 16, 25, 36, 49, 64, 81]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 114,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "16"
      ]
     },
     "execution_count": 114,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "f = lambda x: x * x\n",
    "f(4)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 115,
   "metadata": {},
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'my_func2' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mNameError\u001b[0m                                 Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-115-74b2f4762e1f>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m      1\u001b[0m \u001b[0;31m#2、先调用后定义行吗？\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      2\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\u001b[0;31m \u001b[0mmy_func2\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'hello world'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m      4\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      5\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mmy_func2\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmessage\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;31mNameError\u001b[0m: name 'my_func2' is not defined"
     ]
    }
   ],
   "source": [
    "#2、先调用后定义行吗？\n",
    "\n",
    "my_func2('hello world')\n",
    "\n",
    "def my_func2(message):\n",
    "    print(f'Got a message: {message}')\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 117,
   "metadata": {},
   "outputs": [],
   "source": [
    "def my_func3(message):\n",
    "    aa+=1\n",
    "    my_sub_func(message) # 调用 my_sub_func()在其声明之前不影响程序执行\n",
    "    \n",
    "def my_sub_func(message):\n",
    "    print(f'Got a message: {message}')\n",
    "    \n",
    "#my_func3('hello world')\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 118,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "8\n",
      "[1, 2, 3, 4]\n",
      "编程小妙招\n"
     ]
    }
   ],
   "source": [
    "#3、多态\n",
    "\n",
    "def my_sum(a, b):\n",
    "    #必要时类型检查\n",
    "    return a + b\n",
    "\n",
    "result = my_sum(3, 5)\n",
    "print(result)\n",
    "\n",
    "result = my_sum([1,2], [3,4])\n",
    "print(result)\n",
    "\n",
    "result = my_sum(\"编程\", \"小妙招\")\n",
    "print(result)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 119,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "pass\n"
     ]
    }
   ],
   "source": [
    "# 4、变量的作用域\n",
    "\n",
    "MIN_VALUE = 1\n",
    "MAX_VALUE = 10\n",
    "def validation_check(value):\n",
    "    if value < MIN_VALUE or value > MAX_VALUE:\n",
    "        raise Exception('validation check fails')\n",
    "    print(\"pass\")\n",
    "validation_check(5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 122,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "MIN_VALUE = 1\n",
      "MIN_VALUE = 3\n",
      "MIN_VALUE = 1\n"
     ]
    }
   ],
   "source": [
    "MIN_VALUE = 1\n",
    "MAX_VALUE = 10\n",
    "print(f\"{MIN_VALUE = }\")\n",
    "def validation_check(value):\n",
    "    \n",
    "    MIN_VALUE = 3\n",
    "    print(f\"{MIN_VALUE = }\")\n",
    "\n",
    "validation_check(5)\n",
    "\n",
    "print(f\"{MIN_VALUE = }\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 124,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "inner: nonlocal\n",
      "outer: nonlocal\n"
     ]
    }
   ],
   "source": [
    "def outer():\n",
    "    x = \"local\"\n",
    "    def inner():\n",
    "        nonlocal x \n",
    "        x = 'nonlocal'\n",
    "        print(\"inner:\", x)\n",
    "    inner()\n",
    "    print(\"outer:\", x)\n",
    "outer()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 125,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "hello\n",
      "world\n"
     ]
    }
   ],
   "source": [
    "#5、函数的嵌套\n",
    "def f1():\n",
    "    print('hello')\n",
    "    def f2():\n",
    "        print('world')\n",
    "    f2()\n",
    "f1()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 126,
   "metadata": {},
   "outputs": [],
   "source": [
    "def connect_DB():\n",
    "    def get_DB_configuration():\n",
    "        ...\n",
    "        return host, username, password\n",
    "    conn = connector.connect(get_DB_configuration())\n",
    "    return conn"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 127,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "120\n"
     ]
    }
   ],
   "source": [
    "def factorial(input):\n",
    "    # validation check\n",
    "    if not isinstance(input, int):\n",
    "        raise Exception('input must be an integer.')\n",
    "    if input < 0:\n",
    "        raise Exception('input must be greater or equal to 0' )\n",
    "    ...\n",
    "\n",
    "    def inner_factorial(input):\n",
    "        if input <= 1:\n",
    "            return 1\n",
    "        return input * inner_factorial(input-1)\n",
    "    return inner_factorial(input)\n",
    "\n",
    "\n",
    "print(factorial(5))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 128,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "4\n",
      "8\n"
     ]
    }
   ],
   "source": [
    "# 6、闭包\n",
    "\n",
    "def nth_power(exponent):\n",
    "    def exponent_of(base):\n",
    "        return base ** exponent\n",
    "    return exponent_of # 返回值是exponent_of函数\n",
    "\n",
    "square = nth_power(2) # 计算一个数的平方\n",
    "cube = nth_power(3) # 计算一个数的立方 \n",
    "\n",
    "print(square(2))  # 计算2的平方\n",
    "print(cube(2)) # 计算2的立方\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "[闭包的妙用](https://mp.weixin.qq.com/s/J78x1MPMf7nViqjK1i7E2A)，见评论区"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 129,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Closure\n",
    "def fib():\n",
    "    x1 = 0\n",
    "    x2 = 1\n",
    "    def get_next_number():\n",
    "        nonlocal x1, x2\n",
    "        x3 = x1 + x2\n",
    "        x1, x2 = x2, x3\n",
    "        return x3\n",
    "    return get_next_number"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 130,
   "metadata": {},
   "outputs": [],
   "source": [
    "fibonacci = fib()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 131,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n",
      "2\n",
      "3\n",
      "5\n",
      "8\n",
      "13\n"
     ]
    }
   ],
   "source": [
    "print(fibonacci())\n",
    "print(fibonacci())\n",
    "print(fibonacci())\n",
    "print(fibonacci())\n",
    "print(fibonacci())\n",
    "print(fibonacci())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 132,
   "metadata": {},
   "outputs": [],
   "source": [
    "def fib_recursion(n:int) -> int:\n",
    "    if n <= 1:\n",
    "        return n\n",
    "    return fib_recursion(n-1) + fib_recursion(n-2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 133,
   "metadata": {},
   "outputs": [],
   "source": [
    "def fib_closure(n):\n",
    "    f = fib()\n",
    "    for i in range(2, n+1):\n",
    "        num = f()\n",
    "    return num"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 134,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "6765"
      ]
     },
     "execution_count": 134,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "fib_closure(20)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 135,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "6765"
      ]
     },
     "execution_count": 135,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "fib_recursion(20)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 136,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 8 µs, sys: 1e+03 ns, total: 9 µs\n",
      "Wall time: 11 µs\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "6765"
      ]
     },
     "execution_count": 136,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%time fib_closure(20)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 137,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 2.63 ms, sys: 4 µs, total: 2.64 ms\n",
      "Wall time: 2.64 ms\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "6765"
      ]
     },
     "execution_count": 137,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%time fib_recursion(20)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
